package com.kuangstudy.controller.list;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.kuangstudy.entity.Content;
import com.kuangstudy.service.list.PushContentService;
import com.kuangstudy.vo.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @description:
 * @author: xuke
 * @time: 2021/6/11 23:34
 */
@RestController
public class PushContentController {


    @Autowired
    private PushContentService pushContentService;
    @Autowired
    private RedisTemplate redisTemplate;

    /*
     * @Author xuke
     * @Description 发送微博
     * @Date 23:49 2021/6/11
     * @Param [content]
     * @return com.kuangstudy.vo.R
     **/
    @PostMapping("/sendmsg")
    public R post(@RequestBody Content content) {
        Content content1 = pushContentService.saveContent(content);
        // 推送到首页
        this.pushHomeList(content.getUserId(), content1.getId());
        // 发送一条微博，批量推送给所有的粉丝
        this.pushFollower(content.getUserId(), content1.getId());
        return R.ok().data("content1", content1);
    }


    /*****************************************查看推荐主页 ******************************/
    // 发送一条微博，批量推送给所有的粉丝
    public void pushFollower(Integer userId, Integer postId) {
        // 1: 读取粉丝列表
        SetOperations<String, Integer> setOperations = this.redisTemplate.opsForSet();
        // 读取userid的粉丝列表
        String key = "follower:user:" + userId;
        // 2: 千万不能使用这种方式，因为关注的用户可能是上千万，量太大会撑爆
        //Set<Integer> members = setOperations.members(key);
        Cursor<Integer> scan = setOperations.scan(key, ScanOptions.NONE);
        try {
            while (scan.hasNext()) {
                // 循环遍历每个粉丝的用户id
                Integer followid = scan.next();
                String fkey = "weibo:attention:list:" + followid;
                // 然后为每个粉丝推送消息即可
                this.redisTemplate.opsForList().leftPush(fkey, postId);
                // 性能优化：进行限定处理,如果大于1000就进行截取
                if (this.redisTemplate.opsForList().size(fkey) > 1000) {
                    this.redisTemplate.opsForList().trim(fkey, 0, 1000);
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }


    // 获取个人主页列表
    @GetMapping("/followlist")
    public Page<Content> followlist(Integer userId, int page, int size) {
        Page<Content> page1 = new Page<>(page, size);

        // 1: 计算list分页的起始和结束
        int start = (page - 1) * size;
        int end = start + size - 1;

        String key = "weibo:attention:list:" + userId;
        // 2: 查询用户发微博的总数
        int total = this.redisTemplate.opsForList().size(key).intValue();
        page1.setTotal(total);
        // 3: 查看每页显示的内容
        List<Integer> range = this.redisTemplate.opsForList().range(key, start, end);
        page1.setRecords(getcontents(range));
        return page1;
    }


    /**********************************查看个人主页********************************/

    @PostMapping("/delmsg")
    public R delmsg(Integer userId, Integer postId) {
        String key = "weibo:index:list:" + userId;
        String ckey = "weibo:content:" + postId;
        this.redisTemplate.opsForList().remove(key, 1, postId);
        this.redisTemplate.opsForHash().delete(ckey, "nickname", "id", "avatar", "sendtime", "userId", "content");
        return R.ok();
    }

    // push到个人主页
    public void pushHomeList(Integer userId, Integer postId) {
        String key = "weibo:index:list:" + userId;
        this.redisTemplate.opsForList().leftPush(key, postId);
        // 性能优化：进行限定处理,如果大于1000就进行截取
        if (this.redisTemplate.opsForList().size(key) > 1000) {
            this.redisTemplate.opsForList().trim(key, 0, 1000);
        }
    }

    // 获取个人主页列表
    @GetMapping("/homelist")
    public Page<Content> homeList(Integer userId, int page, int size) {
        Page<Content> page1 = new Page<>(page, size);

        // 1: 计算list分页的起始和结束
        int start = (page - 1) * size;
        int end = start + size - 1;

        String key = "weibo:index:list:" + userId;
        // 2: 查询用户发微博的总数
        int total = this.redisTemplate.opsForList().size(key).intValue();
        page1.setTotal(total);
        // 3: 查看每页显示的内容
        List<Integer> range = this.redisTemplate.opsForList().range(key, start, end);
        page1.setRecords(getcontents(range));
        return page1;
    }

    // 根据存储的文章id到hash中去查询明细
    List<Content> getcontents(List<Integer> postids) {
        List<Content> contentList = new ArrayList<>();

        // 要获取hash的字段值
        List<String> hashKeys = new ArrayList<>();
        hashKeys.add("id");
        hashKeys.add("content");
        hashKeys.add("userId");
        hashKeys.add("nickname");
        hashKeys.add("sendtime");

        HashOperations<String, String, Object> hashOperations = this.redisTemplate.opsForHash();
        for (Integer postid : postids) {
            String key = "weibo:content:" + postid;
            List<Object> objects = hashOperations.multiGet(key, hashKeys);
            if (objects != null && objects.size() > 0) {
                if (objects.get(0) == null && objects.get(1) == null) {
                    // 去db查询
//                    Content content = contentService.getById(postid);
//                    contentList.add(content);
                } else {
                    Content content = new Content();
                    content.setId(postid);
                    content.setContent(String.valueOf(objects.get(1)));
                    content.setUserId(Integer.valueOf(objects.get(2).toString()));
                    content.setNickname(String.valueOf(objects.get(3)));
                    content.setSendtime(Long.valueOf(objects.get(4).toString()));
                    contentList.add(content);
                }
            }
        }

        return contentList;
    }
}
